#pragma once

#include "Timestamp.h"
#include "Poller.h"
#include "CurrentThread.h"
#include "TimerWheel.h" 

#include <memory>
#include <functional>
#include <pthread.h>
#include <atomic>
#include <mutex>

//事件循环类，主要包含两大模块 Channel Poller
class EventLoop
{
public:
    using Functor = std::function<void()>;
    using TaskFunc = std::function<void()>;

    EventLoop();
    ~EventLoop();

    // 开启事件循环
    void loop();
    // 关闭事件循环
    void quit();

    Timestamp pollReturnTime() const { return pollReturnTime_; }

    // 在当前loop中执行cb
    void runInLoop(Functor cb);
    // 把cb放入队列中，唤醒loop所在的线程执行cb
    void queueInLoop(Functor cb);

    // 用来唤醒loop所在的线程
    void wakeup();

    // 调用poller接口
    void updateChannel(Channel* channel);
    void removeChannel(Channel* channel);
    bool hasChannel(Channel *channel);

    // 判断EventLoop对象是否在自己的线程里面
    bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); }

    //时间轮相关
    void timerAdd(std::string name, uint32_t delay, const TaskFunc& cb);
    void timerRefresh(std::string name);
    void timerCancel(std::string name);
    bool hasTimer(std::string name);

private:
    void handleRead();        // wakeupfd的读事件处理函数
    void doPendingFunctors(); // 执行回调，待执行的回调都存放在PendingFunctors_中

private:
    using ChannelList = std::vector<Channel *>;

    std::atomic_bool looping_; // 标识loop正在运行
    std::atomic_bool quit_;    // 标识退出loop循环

    const pid_t threadId_; // 当前loop所在的线程id

    Timestamp pollReturnTime_; // poller返回就绪事件的channels的时间点
    std::unique_ptr<Poller> poller_;

    /**
     * wakeupFd用来唤醒loop所在的线程
     * subloop监听的fd都没有事情发生时，就会阻塞在poll()这，等达到超时时间后才返回（看timeout的值，-1就一直阻塞）
     * 如果这时有新的连接产生，mainloop要分发给subloop，就需要subloop的poll返回后处理完返回的事件，再对新连接处理
     * 不管poll()是一直阻塞直到事情发生返回，还是超时返回，都有一段时间浪费，
     * 所以这里给loop创建一个wakeupfd，用来唤醒阻塞中的subloop。
     * 即loop的poller监听两种fd，一种是用户fd，一种是自己的唤醒fd
     * 当新连接到来时，给wakeupfd写入东西，那么该wakeupfd的读事件就发生，就不会阻塞了
     */
    int wakeupFd_;                           // 一个Loop一个wakeupFd，负责mainloop对subloop进行唤醒
    std::unique_ptr<Channel> wakeupChannel_; // wakeupFd对应的Channel

    ChannelList activeChannels_;

    std::atomic_bool callingPendingFunctors_; // 标识当前loop是否有需要执行的回调操作
    std::vector<Functor> pendingFunctors_;    // 存储loop需要执行的所有的回调操作
    std::mutex mutex_;                        // 互斥锁，用来保护上面vector容器的线程安全操作
    TimerWheel timerWheel_;                   // 定时器模块
};